package cn.alex.sso.project.service.impl;

import cn.alex.sso.project.entity.SysClient;
import cn.alex.sso.project.mapper.StatisticsMapper;
import cn.alex.sso.project.service.StatisticsService;
import cn.alex.sso.project.service.SysClientService;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author Alex
 * @date 2025/1/13 下午1:06
 */
@Service
@RequiredArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {
    private final StatisticsMapper statisticsMapper;
    private final SysClientService clientService;

    @Override
    public Map<String, Object> getTotal() {
        Map<String, Object> result = statisticsMapper.selectTotal();
        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, true);
        result.put("onlineTotal", sessionIdList.size());
        return result;
    }

    @Override
    public List<Map<String, Object>> getClientRankList(Map<String, String> params) {
        return statisticsMapper.selectClientRankList(params);
    }

    @Override
    public Map<String, Object> getClientVisitStc(Map<String, String> params) {
        Map<String, Object> result = new HashMap<>();
        List<String> xAxis = new LinkedList<>();
        List<Map<String, Object>> series = new ArrayList<>();

        Integer type = MapUtil.getInt(params, "type");
        Date startTime = MapUtil.get(params, "startTime", Date.class);
        Date endTime = MapUtil.get(params, "endTime", Date.class);

        String sqlDateFormat = "";
        if (ObjUtil.isNotEmpty(type)) {
            switch (type) {
                case 1:
                case 2:
                case 3:
                    // 今日、本周、本月
                    sqlDateFormat = "%Y-%m-%d";
                    List<DateTime> dayList = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_MONTH);
                    for (DateTime dateTime : dayList) {
                        xAxis.add(DateUtil.format(dateTime, DatePattern.NORM_DATE_PATTERN));
                    }
                    break;
                case 4:
                    // 本年
                    sqlDateFormat = "%Y-%m";
                    List<DateTime> monthList = DateUtil.rangeToList(startTime, endTime, DateField.MONTH);
                    for (DateTime dateTime : monthList) {
                        xAxis.add(DateUtil.format(dateTime, DatePattern.NORM_MONTH_PATTERN));
                    }
                    break;
            }
        } else {
            int startYear = DateUtil.year(startTime);
            int endYear = DateUtil.year(endTime);
            boolean yearBool = startYear == endYear;

            int startMonth = DateUtil.month(startTime);
            int endMonth = DateUtil.month(endTime);
            boolean monthBool = startMonth == endMonth;

            String startDay = DateUtil.format(startTime, "dd");
            String endDay = DateUtil.format(endTime, "dd");
            boolean dayBool = startDay.equals(endDay);

            if (yearBool && monthBool && !dayBool) {
                sqlDateFormat = "%Y-%m-%d";
                List<DateTime> dayList = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_MONTH);
                for (DateTime dateTime : dayList) {
                    xAxis.add(DateUtil.format(dateTime, DatePattern.NORM_DATE_PATTERN));
                }
            } else if (yearBool) {
                sqlDateFormat = "%Y-%m";
                List<DateTime> dayList = DateUtil.rangeToList(startTime, endTime, DateField.MONTH);
                for (DateTime dateTime : dayList) {
                    xAxis.add(DateUtil.format(dateTime, DatePattern.NORM_MONTH_PATTERN));
                }
            } else {
                sqlDateFormat = "%Y";
                List<DateTime> dayList = DateUtil.rangeToList(startTime, endTime, DateField.YEAR);
                for (DateTime dateTime : dayList) {
                    xAxis.add(DateUtil.format(dateTime, DatePattern.NORM_YEAR_PATTERN));
                }
            }
        }

        result.put("xAxis", xAxis);

        List<SysClient> list = clientService.list();
        for (SysClient client : list) {
            Map<String, Object> obj = new HashMap<>();
            obj.put("name", client.getName());
            obj.put("type", "line");

            List<Long> data = new LinkedList<>();

            List<Map<String, Object>> visitList = statisticsMapper.selectClientVisitList(sqlDateFormat, client.getId());
            for (String xAxi : xAxis) {
                Map<String, Object> map = visitList.stream().filter(item -> {
                    String date = MapUtil.getStr(item, "date");
                    return StrUtil.equals(xAxi, date);
                }).findFirst().orElse(null);

                data.add(MapUtil.getLong(map, "count", 0L));
            }

            obj.put("data", data);

            series.add(obj);
        }

        result.put("series", series);
        return result;
    }
}
